package com.vincent.tvui;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;

/**
 * EdgeView can make the focus of the more obvious
 */
public class EdgeView extends View implements ViewTreeObserver.OnGlobalFocusChangeListener {

    private static final int DEFAULT_TRAN_DUR_ANIM = 300;
    private static final float DEFUALT_SCALE = 1.0f;

    private View mFocusContent;
    private float mScale = 1.2f;

    private View mFocusView;
    private View mOldFocusView;

    private boolean mAnimEnabled = true;

    private Drawable mDrawableShadow;
    private Drawable mDrawableBorder;

    private int mHostViewId;

    public EdgeView(Context context) {
        this(context, null, 0);
    }

    public EdgeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public EdgeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray tArray = context.obtainStyledAttributes(attrs, R.styleable.EdgeView);// 获取配置属性
        mDrawableBorder = tArray.getDrawable(R.styleable.EdgeView_border);
        //mDrawableShadow = tArray.getDrawable(R.styleable.EdgeView_shadow);
        mScale = tArray.getFloat(R.styleable.EdgeView_scale, 1.1f);
        mHostViewId = tArray.getResourceId(R.styleable.EdgeView_host, android.R.id.content);
        tArray.recycle();
        setFocusable(false);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        ViewGroup viewGroup = (ViewGroup) getParent();
        if (viewGroup != null) {
            this.mFocusContent = viewGroup.findViewById(mHostViewId);
            if (this.mFocusContent != null) {
                mFocusContent.getViewTreeObserver().addOnGlobalFocusChangeListener(this);
            }
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (this.mFocusContent != null) {
            this.mFocusContent.getViewTreeObserver().removeOnGlobalFocusChangeListener(this);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.save();
        //drawShadow(canvas);
        drawBorder(canvas);
        canvas.restore();
        super.onDraw(canvas);
    }

    //draw shadow
    protected void drawShadow(Canvas canvas) {
        if (mDrawableShadow != null) {
            RectF shadowPaddingRect = new RectF(10, 10, 10, -55);
            int width = getWidth();
            int height = getHeight();
            Rect padding = new Rect();
            mDrawableShadow.getPadding(padding);
            //
            int left = (int) Math.rint(shadowPaddingRect.left);
            int right = (int) Math.rint(shadowPaddingRect.right);
            int bottom = (int) Math.rint(shadowPaddingRect.bottom);
            int top = (int) Math.rint(shadowPaddingRect.top);
            //
            mDrawableShadow.setBounds(-padding.left - (left), -padding.top - (top),
                    width + padding.right + (right),
                    height + padding.bottom + (bottom));
            mDrawableShadow.draw(canvas);
        }
    }

    //draw Border
    protected void drawBorder(Canvas canvas) {
        if (mDrawableBorder != null) {
            RectF paddingRect = new RectF(0, 0, 0, 0);
            int width = getWidth();
            int height = getHeight();
            Rect padding = new Rect();
            // 边框的绘制.
            mDrawableBorder.getPadding(padding);
            //
            int left = (int) Math.rint(paddingRect.left);
            int right = (int) Math.rint(paddingRect.right);
            int bottom = (int) Math.rint(paddingRect.bottom);
            int top = (int) Math.rint(paddingRect.top);
            //
            mDrawableBorder.setBounds(-padding.left - (left), -padding.top - (top),
                    width + padding.right + (right), height + padding.bottom + (bottom));
            mDrawableBorder.draw(canvas);
        }

    }

    public void setWidth(int width) {
        getLayoutParams().width = width;
        requestLayout();
    }

    public void setHeight(int height) {
        getLayoutParams().height = height;
        requestLayout();
    }

    private Rect findLocationWithView(View view) {
        ViewGroup root = (ViewGroup) getParent();
        Rect rect = new Rect();
        root.offsetDescendantRectToMyCoords(view, rect);
        return rect;
    }

    private void flyWhiteBorder(final View focusView, View moveView, float scaleX, float scaleY) {
        int newWidth = 0;
        int newHeight = 0;
        int oldWidth = 0;
        int oldHeight = 0;

        int newX = 0;
        int newY = 0;

        if (focusView != null) {
            // 有一点偏差,需要进行四舍五入.
            newWidth = (int) (Math.rint(focusView.getMeasuredWidth() * scaleX));
            newHeight = (int) (Math.rint(focusView.getMeasuredHeight() * scaleY));
            oldWidth = moveView.getMeasuredWidth();
            oldHeight = moveView.getMeasuredHeight();
            Rect fromRect = findLocationWithView(moveView);
            Rect toRect = findLocationWithView(focusView);
            int x = toRect.left - fromRect.left;
            int y = toRect.top - fromRect.top;
            newX = x - Math.abs(focusView.getMeasuredWidth() - newWidth) / 2;
            newY = y - Math.abs(focusView.getMeasuredHeight() - newHeight) / 2;
        }

        ObjectAnimator transAnimatorX = ObjectAnimator.ofFloat(moveView, "translationX", newX);
        ObjectAnimator transAnimatorY = ObjectAnimator.ofFloat(moveView, "translationY", newY);
        ObjectAnimator scaleXAnimator = ObjectAnimator.ofInt(this, "width", oldWidth, newWidth);
        ObjectAnimator scaleYAnimator = ObjectAnimator.ofInt(this, "height", oldHeight, newHeight);
        AnimatorSet mAnimatorSet = new AnimatorSet();
        mAnimatorSet.playTogether(transAnimatorX, transAnimatorY, scaleXAnimator, scaleYAnimator);
        mAnimatorSet.setInterpolator(new DecelerateInterpolator(1));
        mAnimatorSet.setDuration(DEFAULT_TRAN_DUR_ANIM);

        //添加动画监听
        mAnimatorSet.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (getVisibility() != VISIBLE) {
                    setVisibility(VISIBLE);
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        mAnimatorSet.start();
    }

    @Override
    public void onGlobalFocusChanged(View oldFocus, View newFocus) {
        this.mFocusView = newFocus;

        if (!mAnimEnabled)
            return;

        if (newFocus != null) {
            newFocus.bringToFront();
            newFocus.animate().scaleX(mScale).scaleY(mScale).setDuration(DEFAULT_TRAN_DUR_ANIM).start(); // 放大焦点VIEW的动画.
            flyWhiteBorder(newFocus, this, mScale, mScale); // 移动边框的动画。
        }

        if (this.mOldFocusView != null) {
            mOldFocusView.animate().scaleX(DEFUALT_SCALE).scaleY(DEFUALT_SCALE).setDuration(DEFAULT_TRAN_DUR_ANIM).start();
        }

        mOldFocusView = newFocus; // 4.3以下需要自己保存.
    }
}
